package com.campus.lostandfound;

import com.campus.lostandfound.utils.AesUtil;

import java.util.Scanner;

/**
 * 配置加密工具
 * 用于生成加密的环境变量配置
 */
public class ConfigEncryptionTool {

    private static final Scanner scanner = new Scanner(System.in);
    private static String aesKey;

    public static void main(String[] args) {
        System.out.println("\n========================================");
        System.out.println("配置加密工具 v1.0");
        System.out.println("校园失物招领系统");
        System.out.println("========================================\n");

        // 1. 检查 AES 密钥
        aesKey = System.getenv("AES_ENCRYPTION_KEY");
        if (aesKey == null || aesKey.isEmpty()) {
            System.err.println("✗ 错误: 未检测到 AES_ENCRYPTION_KEY 环境变量");
            System.err.println("\n请先设置环境变量:");
            System.err.println("  Windows: set AES_ENCRYPTION_KEY=your-16byte-key");
            System.err.println("  或在 IDEA 的 Run Configuration 中配置");
            System.err.println("\n密钥要求: 必须是 16 字节（16个字符）");
            return;
        }

        // 验证密钥长度
        try {
            if (aesKey.getBytes("UTF-8").length != 16) {
                System.err.println("✗ 错误: AES 密钥长度必须是 16 字节，当前: " 
                    + aesKey.getBytes("UTF-8").length + " 字节");
                return;
            }
        } catch (Exception e) {
            System.err.println("✗ 错误: 密钥验证失败 - " + e.getMessage());
            return;
        }

        System.out.println("✓ 检测到 AES 密钥: " + maskKey(aesKey));
        System.out.println();

        // 2. 显示菜单
        while (true) {
            showMenu();
            String choice = scanner.nextLine().trim();

            switch (choice) {
                case "1":
                    encryptSingle();
                    break;
                case "2":
                    decryptSingle();
                    break;
                case "3":
                    generateDatabaseConfig();
                    break;
                case "4":
                    generateRedisConfig();
                    break;
                case "5":
                    generateFullEnvFile();
                    break;
                case "6":
                    testEncryptDecrypt();
                    break;
                case "0":
                    System.out.println("\n再见！");
                    return;
                default:
                    System.out.println("✗ 无效的选项，请重新选择\n");
            }
        }
    }

    private static void showMenu() {
        System.out.println("========================================");
        System.out.println("请选择操作:");
        System.out.println("========================================");
        System.out.println("1. 加密单个配置");
        System.out.println("2. 解密配置（验证）");
        System.out.println("3. 批量生成数据库配置");
        System.out.println("4. 批量生成 Redis 配置");
        System.out.println("5. 生成完整环境变量配置");
        System.out.println("6. 测试加密/解密功能");
        System.out.println("0. 退出");
        System.out.println("========================================");
        System.out.print("请输入选项 [0-6]: ");
    }

    /**
     * 加密单个配置
     */
    private static void encryptSingle() {
        System.out.println("\n【加密单个配置】");
        System.out.print("请输入要加密的内容: ");
        String plainText = scanner.nextLine().trim();

        if (plainText.isEmpty()) {
            System.out.println("✗ 内容不能为空\n");
            return;
        }

        try {
            String encrypted = AesUtil.encrypt(plainText, aesKey);
            String wrapped = AesUtil.wrapCiphertext(encrypted);

            System.out.println("\n加密结果:");
            System.out.println(wrapped);
            System.out.println("\n复制上面的完整内容（包括 ENC(...) ）到环境变量中。\n");
        } catch (Exception e) {
            System.err.println("✗ 加密失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 解密配置（验证）
     */
    private static void decryptSingle() {
        System.out.println("\n【解密配置】");
        System.out.print("请输入要解密的内容（ENC(...) 格式）: ");
        String encryptedText = scanner.nextLine().trim();

        if (encryptedText.isEmpty()) {
            System.out.println("✗ 内容不能为空\n");
            return;
        }

        try {
            if (!AesUtil.isEncrypted(encryptedText)) {
                System.out.println("✗ 格式错误，必须是 ENC(...) 格式\n");
                return;
            }

            String ciphertext = AesUtil.extractCiphertext(encryptedText);
            String decrypted = AesUtil.decrypt(ciphertext, aesKey);

            System.out.println("\n解密结果:");
            System.out.println(decrypted);
            System.out.println();
        } catch (Exception e) {
            System.err.println("✗ 解密失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 批量生成数据库配置
     */
    private static void generateDatabaseConfig() {
        System.out.println("\n【批量生成数据库配置】");
        System.out.println("请依次输入以下信息（回车使用默认值）:\n");

        // 数据库 URL
        System.out.print("数据库 URL [jdbc:mysql://localhost:3306/campus_lost_found?...]: ");
        String dbUrl = scanner.nextLine().trim();
        if (dbUrl.isEmpty()) {
            dbUrl = "jdbc:mysql://localhost:3306/campus_lost_found?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
        }

        // 数据库用户名
        System.out.print("数据库用户名 [root]: ");
        String dbUsername = scanner.nextLine().trim();
        if (dbUsername.isEmpty()) {
            dbUsername = "root";
        }

        // 数据库密码
        System.out.print("数据库密码: ");
        String dbPassword = scanner.nextLine().trim();

        System.out.println("\n是否加密数据库配置？(y/n) [y]: ");
        String encryptChoice = scanner.nextLine().trim().toLowerCase();
        boolean shouldEncrypt = encryptChoice.isEmpty() || encryptChoice.equals("y");

        try {
            System.out.println("\n========================================");
            System.out.println("生成的环境变量配置（复制到 IDEA 或 .env）:");
            System.out.println("========================================");

            if (shouldEncrypt) {
                String encryptedUrl = AesUtil.wrapCiphertext(AesUtil.encrypt(dbUrl, aesKey));
                String encryptedPassword = AesUtil.wrapCiphertext(AesUtil.encrypt(dbPassword, aesKey));
                
                System.out.println("DB_URL=" + encryptedUrl);
                System.out.println("DB_USERNAME=" + dbUsername);
                System.out.println("DB_PASSWORD=" + encryptedPassword);
            } else {
                System.out.println("DB_URL=" + dbUrl);
                System.out.println("DB_USERNAME=" + dbUsername);
                System.out.println("DB_PASSWORD=" + dbPassword);
            }

            System.out.println("========================================\n");
        } catch (Exception e) {
            System.err.println("✗ 生成配置失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 批量生成 Redis 配置
     */
    private static void generateRedisConfig() {
        System.out.println("\n【批量生成 Redis 配置】");
        System.out.println("请依次输入以下信息（回车使用默认值）:\n");

        System.out.print("Redis 地址 [localhost]: ");
        String redisHost = scanner.nextLine().trim();
        if (redisHost.isEmpty()) {
            redisHost = "localhost";
        }

        System.out.print("Redis 端口 [6379]: ");
        String redisPort = scanner.nextLine().trim();
        if (redisPort.isEmpty()) {
            redisPort = "6379";
        }

        System.out.print("Redis 密码（没有密码直接回车）: ");
        String redisPassword = scanner.nextLine().trim();

        System.out.print("\n是否加密 Redis 密码？(y/n) [y]: ");
        String encryptChoice = scanner.nextLine().trim().toLowerCase();
        boolean shouldEncrypt = (encryptChoice.isEmpty() || encryptChoice.equals("y")) 
                                && !redisPassword.isEmpty();

        try {
            System.out.println("\n========================================");
            System.out.println("生成的 Redis 配置:");
            System.out.println("========================================");
            System.out.println("REDIS_HOST=" + redisHost);
            System.out.println("REDIS_PORT=" + redisPort);

            if (redisPassword.isEmpty()) {
                System.out.println("REDIS_PASSWORD=");
            } else if (shouldEncrypt) {
                String encrypted = AesUtil.wrapCiphertext(AesUtil.encrypt(redisPassword, aesKey));
                System.out.println("REDIS_PASSWORD=" + encrypted);
            } else {
                System.out.println("REDIS_PASSWORD=" + redisPassword);
            }

            System.out.println("========================================\n");
        } catch (Exception e) {
            System.err.println("✗ 生成配置失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 生成完整环境变量配置
     */
    private static void generateFullEnvFile() {
        System.out.println("\n【生成完整环境变量配置】");
        System.out.println("将生成包含所有配置的环境变量文件内容\n");

        // 数据库配置
        System.out.println("=== 数据库配置 ===");
        System.out.print("数据库 URL: ");
        String dbUrl = scanner.nextLine().trim();
        System.out.print("数据库用户名 [root]: ");
        String dbUsername = scanner.nextLine().trim();
        if (dbUsername.isEmpty()) dbUsername = "root";
        System.out.print("数据库密码: ");
        String dbPassword = scanner.nextLine().trim();

        // JWT 配置
        System.out.println("\n=== JWT 配置 ===");
        System.out.print("JWT 密钥 [campus-lost-found-secret-key-2024]: ");
        String jwtSecret = scanner.nextLine().trim();
        if (jwtSecret.isEmpty()) jwtSecret = "campus-lost-found-secret-key-2024";

        // Redis 配置
        System.out.println("\n=== Redis 配置 ===");
        System.out.print("Redis 地址 [localhost]: ");
        String redisHost = scanner.nextLine().trim();
        if (redisHost.isEmpty()) redisHost = "localhost";
        System.out.print("Redis 端口 [6379]: ");
        String redisPort = scanner.nextLine().trim();
        if (redisPort.isEmpty()) redisPort = "6379";
        System.out.print("Redis 密码（可选）: ");
        String redisPassword = scanner.nextLine().trim();

        try {
            System.out.println("\n========================================");
            System.out.println("完整环境变量配置（IDEA Run Configuration）");
            System.out.println("========================================");
            System.out.println("AES_ENCRYPTION_KEY=" + aesKey + ";");
            System.out.println("JWT_SECRET_KEY=" + jwtSecret + ";");
            System.out.println("DB_URL=" + AesUtil.wrapCiphertext(AesUtil.encrypt(dbUrl, aesKey)) + ";");
            System.out.println("DB_USERNAME=" + dbUsername + ";");
            System.out.println("DB_PASSWORD=" + AesUtil.wrapCiphertext(AesUtil.encrypt(dbPassword, aesKey)) + ";");
            System.out.println("REDIS_HOST=" + redisHost + ";");
            System.out.println("REDIS_PORT=" + redisPort + ";");
            if (!redisPassword.isEmpty()) {
                System.out.println("REDIS_PASSWORD=" + AesUtil.wrapCiphertext(AesUtil.encrypt(redisPassword, aesKey)));
            } else {
                System.out.println("REDIS_PASSWORD=");
            }
            System.out.println("========================================\n");
        } catch (Exception e) {
            System.err.println("✗ 生成配置失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 测试加密/解密功能
     */
    private static void testEncryptDecrypt() {
        System.out.println("\n【测试加密/解密功能】");

        String testText = "Hello, Campus Lost & Found!";
        System.out.println("测试文本: " + testText);

        try {
            // 加密
            String encrypted = AesUtil.encrypt(testText, aesKey);
            String wrapped = AesUtil.wrapCiphertext(encrypted);
            System.out.println("加密后: " + wrapped);

            // 解密
            String ciphertext = AesUtil.extractCiphertext(wrapped);
            String decrypted = AesUtil.decrypt(ciphertext, aesKey);
            System.out.println("解密后: " + decrypted);

            // 验证
            if (testText.equals(decrypted)) {
                System.out.println("\n✓ 测试通过：加密和解密功能正常\n");
            } else {
                System.out.println("\n✗ 测试失败：解密结果不匹配\n");
            }
        } catch (Exception e) {
            System.err.println("✗ 测试失败: " + e.getMessage() + "\n");
        }
    }

    /**
     * 脱敏显示密钥
     */
    private static String maskKey(String key) {
        if (key == null || key.length() < 4) {
            return "****";
        }
        return key.substring(0, 2) + "****" + key.substring(key.length() - 3);
    }
}

